﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using java.math;

namespace EpcTagLibrary
{
    public abstract class EPC
    {
        private byte[] m_Bytes;

        public EPC(Bits bits)
        {
            if (bits != null)
            {
                m_Bytes = Common.BitsToByteArray(bits);
            }
        }

        public EPC(byte[] bytes)
        {
            m_Bytes = new byte[bytes.Length];
            System.Array.Copy(bytes, m_Bytes, bytes.Length);
        }

        public abstract int[] GetFieldSplits();
        public abstract Uri GetTag();
        public abstract Uri GetEPC();

        public abstract string GetScheme();
        public abstract string GetSchemeName();

        public virtual int GetTagBitLength()
        {
            return Common.ByteArrayToBits(m_Bytes).Length;
        }

        public string GetBinaryString()
        {
            return Common.ByteArrayToBits(m_Bytes).ToString();
        }

        public Bits GetBits()
        {
            return Common.ByteArrayToBits(m_Bytes);
        }

        public Uri GetRawHex()
        {
            StringBuilder Result = new StringBuilder();

            BigInteger BI = new BigInteger(this.GetBinaryString(), 2);

            Result.Append("urn:epc:raw:");
            Result.Append(GetTagBitLength());
            Result.Append(".x");

            string Hex = BI.toString(16);

            for (int i = 0; i < Math.Round((decimal)(GetTagBitLength()/4))-Hex.Length; i++)
            {
                Result.Append("0");
            }

            return new Uri(Result.ToString());
        }

        public Uri GetRawDecimal()
        {
            StringBuilder Result = new StringBuilder();

            Result.Append("urn:epc:raw:");
            Result.Append(GetTagBitLength());
            Result.Append(".");

            BigInteger BI = new BigInteger(GetBinaryString(), 2);
            Result.Append(BI.toString(10));

            return new Uri(Result.ToString());
        }

        public Bits GetFieldBits(int fieldIndex)
        {
            Bits Bts = GetBits();

            try
            {
                int[] Splits = GetFieldSplits();
                Bits[] Fields;

                if (Splits.Length > 0)
                {
                    Fields = new Bits[Splits.Length + 1];

                    int LastIdx = Bts.Length;

                    for (int i = 0; i < Splits.Length; i++)
                    {
                        Fields[i] = Bts.GetBits(Splits[i], LastIdx - 1);
                        LastIdx = Splits[i];
                    }

                    Fields[Fields.Length - 1] = Bts.GetBits(0, LastIdx - 1);
                    return Fields[fieldIndex];
                }
            }
            catch (Exception)
            {
            }

            return null;
        }

        public override int GetHashCode()
        {
            if (m_Bytes == null)
            {
                return 0;
            }

            int Result = 0;
            foreach (byte b in m_Bytes)
            {
                Result = 31 * Result + b;
            }

            return Result;
        }

        public override bool Equals(object obj)
        {
            if (obj == this)
            {
                return true;
            }

            if ((obj == null) || !(obj is EPC))
            {
                return false;
            }

            EPC Epc = obj as EPC;

            return (m_Bytes.Equals(Epc.m_Bytes));
        }

        public override string ToString()
        {
            StringBuilder Result = new StringBuilder(GetTagBitLength() + 200);
            Result.Append("EPC {scheme=");
            Result.Append(GetScheme());
            Result.Append(", bitLength=");

            Result.Append(Common.ByteArrayToBits(m_Bytes).Length);

            Result.Append(", bits=[");
            Result.Append(Common.ByteArrayToBits(m_Bytes).ToString());
            Result.Append("]");

            return Result.ToString();
        }
    }

}